import re
import time
from django.core.cache import cache
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
from myTool.tools import get_ip_info
from log.models import RequestLogTable
from threading import Thread

'''
中间件的基本流程:
1.在工程目录下创建一个middleware目录
2.在middleware中创建一个Python文件
3.在这个Python文件中创建一个类，继承自django内置的中间件MiddlewareMixin(伪装)
4.注册，在工程的配置文件settings中找到MIDDLEWARE的配置，将这个类的路径添加到MIDDLEWARE列表里面
5.封装类方法
'''


class MyMiddleWare(MiddlewareMixin):
    def process_request(self, request):
        # return HttpResponse('台维护，暂停访问...')
        requestPath = request.path
        ip = request.META.get('REMOTE_ADDR', '')  # 客户端的ip地址
        flag = re.search(
            r'/login/|/register/|error|learningPlanet|playingPlanet/\d+$|modifyBlog|search/|personalCenter|^/$',
            requestPath)
        # 记录 登录页面 注册页面 错误页面 学习星球页面 快乐星球页面 博客编辑页面 搜索功能 个人中心页面 首页 的请求
        if flag:  # 如果没有undefined才保存该记录
            HTTP_USER_AGENT = request.META.get('HTTP_USER_AGENT', '')  # 请求头
            HTTP_REFERER = request.META.get('HTTP_REFERER', '')  # 访问本网页前的网页地址
            # Thread(target=RequestLogTable.create_request_log,args=(ip, HTTP_USER_AGENT, HTTP_REFERER, requestPath, *get_ip_info(ip))).start()

        # # 实现限制某个时间段内的访问次数(例:1分钟内只能访问60次)
        ip_list = cache.get(ip, [])

        # 时间限制在1分钟 (比较最新的请求和最早的请求的时间差，如果大于60秒，则踢出最早的请求)
        # 如果ip列表的长度大于30，就处于封禁状态，就不能进行pop操作
        while ip_list and time.time() - ip_list[-1] > 60 and len(ip_list) < 30:
            ip_list.pop()

        # 最新的请求添加到请求列表的头部，那么最早的请求就在列表的尾部
        ip_list.insert(0, time.time())

        # 将请求列表保存在缓存中
        response = None
        if len(ip_list) <= 30:
            cache.set(ip, ip_list, timeout=60)

        if len(ip_list) > 30:
            cache.set(ip, ip_list, timeout=60 * 30)  # 封禁30分钟
            response = HttpResponse('大哥，喝杯茶休息一下吧！===><a href="https://baike.baidu.com/item/%E5%92%96%E5%95%A1/29518">🍵</a>')

        # # 次数限制在50次
        if len(ip_list) > 50:
            cache.set(ip, ip_list, timeout=60 * 60 * 2)  # 封禁两个小时
            response = HttpResponse('大哥，我们去看个电影吧！===><a href="https://www.maoyan.com/">📽️</a>')

        # 次数限制在100次
        if len(ip_list) > 100:
            cache.set(ip, ip_list, timeout=60 * 60 * 24)  # 封禁一天
            response = HttpResponse('大哥，不早了，睡觉觉吧！===><a href="https://ctrip.com/">🏨</a>')

        return response

    # 界面友好化处理(当服务器出现异常，状态码为500时，为了不让用户知道服务器的故障，可以使用中间件对此进行处理)
    # def process_exception(self, request, exception):
    #     errInfo = f'客户端ip:{request.META.get("REMOTE_ADDR")},\n错误原因:{exception}'
    #
    #     try:
    #         errObj = ErrTable()
    #         errObj.ip = request.META.get('REMOTE_ADDR')
    #         errObj.path = request.path
    #         errObj.reason = errInfo
    #         errObj.userAgent = request.META['HTTP_USER_AGENT']
    #         errObj.save()
    #
    #     except:
    #         print('未知错误!')
    #     # 如果报错，将页面重定向到指定页面
    #     return redirect(reverse('app:error'))
